//
// Created by 17775 on 2024/10/30.
//

#include "Divergence.h"

void Divergence::stopDivergence() const {
    RayCi_Divergence_Recording_stop(_iDivergenceDocId);
//    if (getDivergenceDataThreadRunning.load(std::memory_order_acquire)) {
//        stopDivergenceThread();
//    }
}

void Divergence::stopDivergenceThread() {
    getDivergenceDataThreadRunning.store(false, std::memory_order_release);
    if (m_divergenceThread.joinable()) {
        m_divergenceThread.join();
    }
}

void Divergence::clearDivergence() const {
    RayCi_Divergence_Recording_clear(_iDivergenceDocId);
}

void Divergence::setFrameSpan(int frames) const {
    bool bFrameSpanAvailable = false;
    RayCi_Divergence_Recording_Settings_isFrameSpanAvailable(_iDivergenceDocId, &bFrameSpanAvailable);
    if(bFrameSpanAvailable) {
        RayCi_Divergence_Recording_Settings_setFrameSpan(_iDivergenceDocId, frames);
    }
}

void Divergence::setSingleShot(bool bEveryFrame) const {
    RayCi_Divergence_Recording_Settings_setSingleShot(_iDivergenceDocId, bEveryFrame);
}

void Divergence::setTimeSpan(double dTime) const {
    bool bTimeSpanAvailable = false;
    RayCi_Divergence_Recording_Settings_isTimeSpanAvailable(_iDivergenceDocId, &bTimeSpanAvailable);
    if(bTimeSpanAvailable) {
        dTime == 0 ? RayCi_Divergence_Recording_Settings_setSingleShot(_iDivergenceDocId, true) :
        RayCi_Divergence_Recording_Settings_setTimeSpan(_iDivergenceDocId, dTime);
    }
}

//void Divergence::getData() {
//    getDivergenceDataThreadRunning.store(true, std::memory_order_release);
//    m_divergenceThread = std::thread(&Divergence::getAllData, this);
//}

//void Divergence::getAllData() {
//    int preLength = 0;
//    while (getDivergenceDataThreadRunning.load(std::memory_order_acquire)) {
//        int dataLength = 0;
//        bool bRecording = false;
//        RayCi_Divergence_Recording_isRecording(_iDivergenceDocId, &bRecording);
//        if(!bRecording) {
//            getDivergenceDataThreadRunning.store(false, std::memory_order_release);
//            emit divergenceMeasurementOver();
//        }
//       RayCi_Divergence_Chart_Data_getDataLength(_iDivergenceDocId, &dataLength);
//    }
//}

// Recording
QString Divergence::getRecordingRemark() const {
    char szRemark_buffer[80] = {0};
    int nSize = sizeof(szRemark_buffer);
    bool success = RayCi_Divergence_Recording_getRemarkA(_iDivergenceDocId, szRemark_buffer, &nSize);
    return success ? QString::fromLatin1(szRemark_buffer) : QString();
}

void Divergence::setPosition(double dPosition) const {
    RayCi_Divergence_Recording_Settings_setPosition(_iDivergenceDocId, dPosition);
}

// Sequence
int Divergence::getCurrentItem() const {
    int nCurrentItem = 0;
    RayCi_Divergence_Sequence_getCurrentItem(_iDivergenceDocId, &nCurrentItem);
    return nCurrentItem;
}

int Divergence::getItemCount() const {
    int nItemCount = 0;
    RayCi_Divergence_Sequence_getItemCount(_iDivergenceDocId, &nItemCount);
    return nItemCount;
}
void Divergence::setCurrentItem(const int index) const {
    if(index < 0 || index >= getItemCount()) return;
    RayCi_Divergence_Sequence_setCurrentItem(_iDivergenceDocId, index);
}

QString Divergence::getItemInfo(int index) const {
    char szInfo_buffer[80] = {0};
    int nSize = sizeof(szInfo_buffer);
    RayCi_Divergence_Sequence_Item_getInfoA(_iDivergenceDocId, index, szInfo_buffer, &nSize);
    return QString::fromLatin1(szInfo_buffer);
}

// Analysis
DivergenceResult Divergence::getDivergenceResult() const {
    DivergenceResult divergenceResult;
    RayCi_Divergence_Sequence_getItemCount(_iDivergenceDocId, &divergenceResult.dCount);
    bool bDivergenceValid = false;
    bool bDivergenceUncertaintyValid = false;
    bool bZeroPointValid = false;
    bool bZeroPointUncertaintyValid = false;
    RayCi_Divergence_Analysis_Divergence_isValid(_iDivergenceDocId, false, &bDivergenceValid);
    RayCi_Divergence_Analysis_Divergence_isValid(_iDivergenceDocId, true, &bDivergenceUncertaintyValid);
    RayCi_Divergence_Analysis_ZeroPoint_isValid(_iDivergenceDocId, false, &bZeroPointValid);
    RayCi_Divergence_Analysis_ZeroPoint_isValid(_iDivergenceDocId, true, &bZeroPointUncertaintyValid);
    if (bZeroPointValid) {
        RayCi_Divergence_Analysis_Divergence_getUX(_iDivergenceDocId, false, &divergenceResult.dDivergenceUX);
        RayCi_Divergence_Analysis_Divergence_getVY(_iDivergenceDocId, false, &divergenceResult.dDivergenceUY);
    }
    if (bDivergenceUncertaintyValid) {
        RayCi_Divergence_Analysis_Divergence_getUX(_iDivergenceDocId, true, &divergenceResult.dDivergenceUncertaintyUX);
        RayCi_Divergence_Analysis_Divergence_getVY(_iDivergenceDocId, true, &divergenceResult.dDivergenceUncertaintyUY);
    }
    if (bZeroPointValid) {
        RayCi_Divergence_Analysis_ZeroPoint_getUX(_iDivergenceDocId, false, &divergenceResult.dZeroPointUX);
        RayCi_Divergence_Analysis_ZeroPoint_getVY(_iDivergenceDocId, false, &divergenceResult.dZeroPointUY);
    }
    if (bZeroPointUncertaintyValid) {
        RayCi_Divergence_Analysis_ZeroPoint_getUX(_iDivergenceDocId, true, &divergenceResult.dZeroPointUncertaintyUX);
        RayCi_Divergence_Analysis_ZeroPoint_getVY(_iDivergenceDocId, true, &divergenceResult.dZeroPointUncertaintyUY);
    }
    return divergenceResult;
}

void Divergence::exportReport() {
    OPENFILENAMEA ofn;
    char szFile[260] = { 0 };
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = nullptr;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile) / sizeof(szFile[0]) - 1;
    ofn.lpstrFilter = "PDF Files(*.pdf)\0*.pdf*\0All Files(*.*)\0*.*\0\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrInitialDir = "C";
    ofn.lpstrTitle = "Save Report As";
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;
    if (GetSaveFileNameA(&ofn) == TRUE) {
        const char* reportPathName = ofn.lpstrFile;
        std::string reportPathWithExtension = std::string(reportPathName) + ".pdf";
        RayCi_Divergence_Report_exportA(_iDivergenceDocId, reportPathWithExtension.c_str());
        ShellExecuteA(nullptr, "open", reportPathWithExtension.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
    } else {
        MessageBoxA(nullptr, "Export was cancelled.", "Info", MB_OK | MB_ICONINFORMATION);
    }
}

void Divergence::close(bool bWaitWhileClosing) {
    RayCi_Divergence_close(_iDivergenceDocId, bWaitWhileClosing);
}
